perm filename TCPPP.MAC[IP,SYS] blob sn#680226 filedate 1982-10-14 generic text, type T, neo UTF8
;CWL:<403-TCP>TCPPP.MAC.40303 26-Apr-82 17:28:04, Edit by CLYNN
; Added PRNPKI for IP calls (saves & zeros TCB)
;<403-TCP>TCPPP.MAC.40301 29-Jan-82 15:06:39, Edit by CLYNN
; Updated for TCP release 3
;[BBNF]<402-INET>INPP.MAC.22, 20-Jul-81 15:59:00, Ed: CLYNN
; Fix: For use in multi-section machines, Beware too many options,
; Don't compare fake free storage header at LCLPKT

	SEARCH	INPAR,TCPPAR,PROLOG
	TTITLE	TCPPP
	SUBTTL	Packet Printer, William W. Plummer, 23FEB77
	SWAPCD

COMMENT	!

	PRNPKT is called from the TCP and IP each time it is fondled
	by some task.  If the current packet is different than the
	one which is stored in the PPBUF, or T1 contains an extended
	code PPBUF is dumped via TCPPDP (instead of the DBGIM (JSYS)
	code in IMPDV), and the current packet is stored in PPBUF.
	If the current packet is the same as that in PPBUF, a record
	is kept regarding what has been done to it and the state of
	the TCB to which it belongs so that when it is finally dumped,
	the most recent information is available.  This minimizes the
	number of printed lines which the usermode program which
	actually prints the formated script will have to print.

* PPINI ...  3 ...... Initialize the packet printer
  RSTPPB ..  3 ...... Reset the buffer state
  DMPBUF ..  3 ...... Dump the current PPBUF

* PRNPKI ..  4 ...... Main routine called from IP
* PRNPKT ..  4 ...... Main routine called from TCP
  PKTPRN ..  4 ...... Do the work with the PPBLCK set

	Debugging aids used in conjunction with MDDT

  TCPPSC ..  8 ...... Close simulation file
  TCPPSO ..  8 ...... Open simulation file
  TCPPSF ..  8 ...... Free packets read from simulation file
  TCPPSR ..  9 ...... Read packet from simulation file

  TCPPIN .. 10 ...... Initialize in-core trace facility
  TCPPSS .. 10 ...... Save packets in in-core buffer for later simulation
  TCPPDP .. 11 ...... Copy PPBUF to in-core buffer
  TCPPWR .. 11 ...... Write-out anything in in-core buffer

	!

; PPINI			; Initialize the Packet Printer
;
;	CALL PPINI
;Ret+1:	Always

PPINI::	PUSH P,FR
	PUSH P,BFR
	XMOVEI BFR,PPBUF
	CALL RSTPPB		; Reset the buffer
	SETZM NXTLBL		; Label number for LBLOPT in packets
	XMOVEI T1,PPBLCK	; Lock on buffer accesses
	CALL CLRLCK		; Reset that
	POP P,BFR
	POP P,FR
	RET




; RSTPPB		; Reset the Packet Printer Buffer state

;FR/	Packet Printer flag word (modified here)
;BFR/	Pointer to packet printer buffer
;	CALL RSTPPB
;Ret+1:	Always.

RSTPPB:	MOVX FR,PP%MT	; Mark buffer as empty, clear all others
	STOR FR,DFLAG,(BFR)	; Store in PPB Flag word
	RET



; DMPBUF		; Dump what's in PPBUF through IMPDV

;FR/	Packet Printer flag word
;BFR/	Pointer to packet printer buffer
;	CALL DMPBUF
;Ret+1:	Always

DMPBUF:	STOR FR,DFLAG,(BFR)	; Update display flags before output
	MOVX T1,PPBWDS		; Number of words in the buffer
	HRRM T1,PPBUF		; Fake an NCP buffer header (keep code)
	XMOVEI T1,PPBUF		; This looks like an NCP Packet buffer
	CALLRET TCPPDP		; Use our routine instead of DBGIN
;	CALLRET DBGIN

; PRNPKI/T	Main Routine, called from all over the IP/TCP

;TCB/	0 or (ext) pointer to Locked connection block (TCP only)
;PKT/	0 or (ext) pointer to packet to print
;T1/	Number saying where the call is from and why
;
;	MOVX T1,PT%xxx
;	TDNE T1,INTTRC
;	  CALL PRNPKI/T
;Ret+1:	Always

PRNPKI::PUSH P,TCB
	SETZ TCB,
	CALL PRNPKT
	POP P,TCB
	RET

PRNPKT::SKIPN INTTRC		; Tracing packets right now?
	  RET			; No.
	MOVE T3,T1		; Setup for call via LCKCAL
	MOVE T4,TODCLK		; When the report is happening
	XMOVEI T1,PPBLCK	; Lock to set (section 0)
	XMOVEI T2,PKTPRN	; (Extended) Function to call
	CALLRET LCKCAL		; Lock the lock and call the function

; PKTPRN	; Action routine

;TCB/	0 or (ext) pointer to locked connection block
;PKT/	0 or (ext) pointer to packet
;T1/	Where report is coming from (PT%xxx)
;T2/	When report is happening (milliseconds)
;
;	Call PKTPRN
;Ret+1:	Always.

PKTPRN::LOCAL <WHERE,WHEN,COUNT,STATE>
	PUSH P,BFR		; BFR pointer for caller
	PUSH P,FR		; Save flag register
	XMOVEI BFR,PPBUF	; Set pointer to buffer
	LOAD FR,DFLAG,(BFR)	; Get local copy of PPB flags
	MOVEM T1,WHERE		; Save args in safe places
	MOVEM T2,WHEN

	JUMPN PKT,PKTPR1	; Jump unless it is BG flushing buffer
	TXNE FR,PP%MT		; Is the buffer empty?
	  JRST PKTPRX		; Yes. Nothing to do.
	CALL DMPBUF		; Dump the buffer via IMPDV
	CALL RSTPPB		; Reset buffer state
	JRST PKTPRX		; Return

PKTPR1:	TXNE FR,PP%MT		; PPB empty?
	  JRST PKTPR4		; Yes.  Just dump in this one
	LOAD T1,PIDO,(PKT)	; Internet Data Offset
	MOVE T2,PKT		; Locate TCP header
	ADD T2,T1
	LOAD T2,PTDO,(T2)	; TCP Data Offset
	ADD T1,T2		; Total number of Header words
	CAILE T1,<PPBFSZ+LCLPKT-PKTELI> ; Beware too many options
	  MOVEI T1,<PPBFSZ+LCLPKT-PKTELI> ; Clamp at PPBUF limit
	SOS T1			; Skip first word
	MOVEM T1,COUNT		; Number of words to compare

	CAIN WHERE,8		; Retransmitter calling?
	 JRST PKTPR3		; Yes.  Force printing

	MOVN T1,COUNT		; Number of full header words
	HRLZS T1		; Make AOBJN pointer
	XMOVEI T2,PKTELI+1(PKT)	; Beginning of corresponding part of hdr
PKTPR2:	MOVE T3,0(T2)		; Get a header word from packet
	CAME T3,PPBUF+PKTELI+1-LCLPKT(T1) ; Same as header in the buffer?
	 JRST PKTPR3		; No.  Dump the buffer
	ADDI T2,1		; Bump the packet pointer
	AOBJN T1,PKTPR2		; Loop over the buffer
	JRST PKTPR4

PKTPR3:	CALL DMPBUF		; Dump the buffer
	CALL RSTPPB		; Reset it

PKTPR4:	TXZN FR,PP%MT		; Is the buffer empty?
	 JRST PKTPR5		; No.  Just update state

	MOVX T1,PPBFSZ-1	; Skip first word (fake header)
	XMOVEI T2,LCLPKT+1(PKT)	; Beginning of real header info(+1)
	XMOVEI T3,PPBUF+1	; Corresponding place in buffer
	CALL XBLTA		; Copy the header into the buf
	STOR WHEN,DTIME,(BFR)	; Save the report time
	STOR PKT,DPKTP,(BFR)	; Save buffer address

PKTPR5:	SKIPE STATE,TCB		; Use 0 for state if no TCB
	  LOAD STATE,TSTAT,(TCB) ; Else get the actual state
	TXZ FR,PP%DUN
	HRRZS (BFR)		; Clear prior extended trace code
	CAILE WHERE,0
	CAILE WHERE,8		; Good value for where?
	 TXOA FR,PP%DUN		; Say we are done with this packet
	  XCT WHRTAB-1(WHERE)
;	TCPBUG(CHK,<Bad arg to PRNPKT>,TCPPP1)
	HRLM WHERE,(BFR) ;****	; Save extended trace code
	JRST PKTPR6

WHRTAB:	JRST WHR1
	JRST WHR2
	JRST WHR3
	JRST WHR4
	JRST WHR5
	JRST WHR6
	JRST WHR7
	JRST WHR8

WHR1:	TXO FR,<PP%PZ!PP%GSS!PP%SK>	; PZ output a packet
	STOR STATE,DSS,(BFR)	; Store source state
	JRST PKTPR6

WHR2:	TXO FR,PP%GSS		; OP reporting
	STOR STATE,DSS,(BFR)

WHR7:	TXO FR,<PP%SNT!PP%SK>	; IP sent RESET based on input packet
	JRST PKTPR6

WHR3:	TXO FR,<PP%RCV!PP%GDS!PP%DK>	; IP, normal
	STOR STATE,DDS,(BFR)	; Store destination state
	JRST PKTPR6

WHR4:	TXO FR,<PP%RA!PP%DK!PP%GDS!PP%DUN> ; RA
	STOR STATE,DDS,(BFR)
	JRST PKTPR6

WHR8:	TXO FR,<PP%REX!PP%GSS!PP%SK>	; RX
	STOR STATE,DSS,(BFR)
	JRST PKTPR6

WHR6:	TXO FR,PP%GDS		; IP, flushed (DUP, IGN, RST, nothing
	STOR STATE,DDS,(BFR)	; to be RA'd) (have TCB)

WHR5:	TXO FR,<PP%DK!PP%DUN>	; IP, flushed (checksum error, CHKADR
				; failed) (no TCB)
PKTPR6:

	TXNN FR,PP%DUN		; Has pkt reached the end of the line?
	 JRST PKTPRX		; No.
	CALL DMPBUF		; Yes.  Dump it now
	CALL RSTPPB		; Reset the buffer

PKTPRX:	STOR FR,DFLAG,(BFR)	; Save the PPB flags
	POP P,FR
	POP P,BFR
	RESTORE
	RET
; Debugging and tracing utilities (used from MDDT)

; Read packets from file & insert where desired

; CALL TCPPSO$X		to Open file for Simulation
; <file name>
; <SKIP> if OK

; CALL TCPPSR		to Read the next Simulated packet
; <SKIP> if OK with PKT set

; CALL SNDGAT$X ,e.g. to send the packet

; CALL TCPPSC		to Close the Simulation file and
; CALL TCPPSF		to Free the Simulated packets


TCPPSO:	CALL TCPPSC		; Open Simulation file (close old one)
	MOVX T1,<GJ%OLD+GJ%FNS+GJ%SHT>
	MOVX T2,<.PRIIN,,.PRIOU>
	GTJFN			; Get name from TTY: (MDDT)
	  RET
	MOVEM T1,TCPPSJ
	MOVX T2,<FLD(↑D36,OF%BSZ)+OF%RD>
	OPENF			; Open file for reading
	  RET
	AOS (P)			; OK return skips
	RET


TCPPSC:	SETZ T1,		; Close Simulation file
	EXCH T1,TCPPSJ
	SKIPE T1
	 CLOSF
	  JFCL
	RET


TCPPSF:	MOVE T1,TCPPSQ		; Free packets from Simulation Queue
	JUMPE T1,TCPPSV
	JN PINTL,(T1),TCPPSV
	MOVE T2,PKTQ(T1)
	MOVEM T2,TCPPSQ
	CALL RETBLK
	JRST TCPPSF

TCPPSR:	MOVE T1,TCPPSJ		; Read next packet from Simulation file
	BIN
	  ERJMP TCPPSV
	HLRZ T1,T2		; Free size
	JUMPLE TCPPSV
	PUSH P,T1
	CALL GETBLK		; Get storage for packet
	MOVEM T1,PKT
	MOVN T3,(P)
	POP P,(P)
	JUMPLE PKT,TCPPSV
	MOVE T1,TCPPSJ
	MOVX T2,<POINT 36,(PKT)>
	SIN			; Read packet into it
	  ERJMP TCPPSU
	SETONE PPROG,(PKT)	; We will hang on to packet
	MOVE T1,TCPPSQ		; (may want to try again)
	MOVEM T1,PKTQ(PKT)
	MOVEM PKT,TCPPSQ	; Place it in our queue
	MOVE T1,TCPPSA
	JFCL			; Maybe not fake address
	  STOR T1,PIDH,(PKT)	; Fake the address
	AOS (P)
	RET

TCPPSU:	MOVE T1,PKT		; Lose, free packet
	CALL RETBLK
TCPPSV:	RET

; In-core trace facility
; IMP trace:	DBGS1B+2/	JFCL
;		DBGS1B+3/	JFCL
;		DBGS1B+4/	MOVEM T2,(T1)

;	&	DBGCK1+2/	MOVEI T1,2(T2)
;		DBGCK1+3/	ADDB T1,TCPPTC
;		DBGCK1+4/	SUBI T1,3(T2)
;		DBGCK1+5/	MOVEM T1,DBGSP
;		DBGCK1+6/	AOS -1(P)

; and set DBGERR and/or DBGNCP non-zero


TCPPIN::MOVX T1,40000		; Size of core buffer
	CALL GETBLK
	JUMPE T1,TCPPIX		; Lose
	XMOVEI T2,<40000-2*PPBWDS>(T1)	; End, allow room for DBG
	MOVEM T2,TCPPTE
	MOVEM T1,TCPPTC
	MOVEM T1,TCPPTB
	SETZM TCPPTO
TCPPIX:	RET


; Create a file of packets from some point in code (XXX:)
; Initialize trace with trace off & when done CALL TCPPWR
; xxx:	CALL TCPPSS

TCPPSS:	JFCL	; c(XXX)
	CAIE T1,-1		; Fill in with desired values
	 CAIN T1,-1		; if filtering desired
	  CAIA
	   RET
	XMOVEI T2,(PKT)		; Beginning of packet
	HLRZ T1,-1(PKT)		; Free storage block length
	JRST TCPPDP+2		; Dump <N,,garb>,N<data>


TCPPDP:	  MOVEI T1,PPBWDS	; PPBUF size
	  XMOVEI T2,PPBUF	; Where from
	HLLZ T3,TCPPTC
	SKIPN T3		; Enforce IF2 above
	  RET			; Don't allow into section zero
	MOVE T3,T1		; Be careful of TCPPTC, both
	ADDB T3,TCPPTC		; TCPPDP and DBGCKS use it w/o lock
	SUB T3,T1		; Where to dump
	CALL XBLTA		; Copy
;	CAMGE T3,TCPPTE		; If more room
;	  MOVEM T3,TCPPTC	;   update end pointer
	CAMGE T3,TCPPTE
	  RET			;   and return
	MOVEM T3,TCPPTO		; Save overflow address and
				; Fall into write routine
TCPPWR:
	MOVX T1,<GJ%OLD+GJ%SHT>
	HRROI T2,TCPPFN		; File name
	GTJFN
	  JRST TCPPWX		; Quit
	MOVX T2,<FLD(↑D36,OF%BSZ)+OF%APP> ; Open for 36 bit append
	OPENF
	  JRST TCPPWX

	MOVE T4,TCPPTB		; Extended start address
	MOVSI T2,(POINT 36,0(T4)) ; & pointer to it

	MOVE T3,TCPPTO		; Possible end
	SKIPG T3		; If not zero
	  MOVE T3,TCPPTC	; If zero, use current
	SUB T3,TCPPTB		; Length, w
	MOVN T3,T3		; Count
	SOUT
	CLOSF
	  JFCL
TCPPWX:	MOVE T4,TCPPTB		; Extended start address
	MOVEM T4,TCPPTC		; is where to start over
	SETZM TCPPTO		; No overflow
	RET

	TNXEND
	END